package com.kmxd.ams.controller.system.login;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.kmxd.ams.app.event.AmsEventPublisher;
import com.kmxd.ams.client.event.log.LoginLogEvent;
import com.kmxd.ams.client.system.ISysUserLoginSvc;
import com.kmxd.ams.client.system.dto.ChangePasswordDTO;
import com.kmxd.ams.client.system.dto.LoginDTO;
import com.kmxd.ams.client.system.vo.AuthPermissionVO;
import com.kmxd.ams.client.system.vo.LoginCaptchaVo;
import com.kmxd.ams.client.system.vo.LoginVO;
import com.kmxd.ams.core.common.constant.CacheConst;
import com.kmxd.ams.core.common.enums.LogLevelEnum;
import com.kmxd.ams.core.common.enums.LogTypeEnum;
import com.kmxd.ams.core.common.enums.LoginTypeEnum;
import com.kmxd.ams.core.log.annotation.AutoLog;
import com.kmxd.ams.core.result.R;
import com.kmxd.ams.core.util.RedisUtils;
import com.wf.captcha.ArithmeticCaptcha;
import com.wf.captcha.base.Captcha;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * 登录 前端控制器
 *
 * @author admin
 */
@Slf4j
@RestController
@RequestMapping("/system")
@AllArgsConstructor
@Tag(name = "用户登录")
public class SysUserLoginCtl {

  private final AmsEventPublisher amsEventPublisher;
  private ISysUserLoginSvc sysUserLoginSvc;
  private RedisUtils redisUtils;

  @Operation(summary = "用户登录")
  @PostMapping("/login")
  @AutoLog(
      module = "授权管理",
      type = LogTypeEnum.LOGIN,
      level = LogLevelEnum.HIGH_RISK,
      title = "登录",
      isSaveRequestData = false)
  public R<LoginVO> login(@Validated @RequestBody LoginDTO req) {
    // debug环境跳过验证码
    if ((!log.isDebugEnabled() || StrUtil.isNotBlank(req.getVerCode())) && StrUtil.equals(req.getGrantType(), LoginTypeEnum.WEB.getType())) {
      // 获取redis中的验证码
      String redisCode =
          StrUtil.toString(redisUtils.get(CacheConst.REDIS_PREFIX + req.getVerKey()));
      // 判断验证码
      if (StrUtil.isBlank(req.getVerCode())
          || !redisCode.equals(req.getVerCode().trim().toLowerCase())) {
        amsEventPublisher.publishEvent(
            new LoginLogEvent("登录", 2, req.getUsername(), "账号密码登录", "验证码不正确"));
        return R.fail("验证码不正确！");
      }
      redisUtils.del(CacheConst.REDIS_PREFIX + req.getVerKey());
    } else {
      log.debug("当前环境为测试环境，跳过验证码校验,线上请切换环境:{}", log.isDebugEnabled());
    }
    return R.success(sysUserLoginSvc.login(req));
  }

  @Operation(summary = "获取验证码-返回base64")
  @GetMapping("/captcha")
  public R<LoginCaptchaVo> captcha(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    String verKey = IdUtil.fastSimpleUUID();

    // 算术类型
    ArithmeticCaptcha captcha = new ArithmeticCaptcha(130, 48);
    // 几位数运算，默认是两位
    captcha.setLen(2);
    // 获取运算的公式：3+2=?
    captcha.getArithmeticString();
    captcha.setCharType(Captcha.TYPE_DEFAULT);
    String verCode = captcha.text().toLowerCase();
    // 存入redis并设置过期时间为2分钟
    redisUtils.set(CacheConst.REDIS_PREFIX + verKey, verCode, 120);

    // 将key和base64返回给前端
    return R.success(
        LoginCaptchaVo.builder().verKey(verKey).verCodeImg(captcha.toBase64()).build());
  }

  @Operation(summary = "退出")
  @PostMapping("/logout")
  public R<Void> logout() {
    try {
      StpUtil.logout();
    } catch (Exception ex) {
    }
    return R.success();
  }

  @Operation(summary = "修改密码")
  @PostMapping("/changePassword")
  @AutoLog(
      module = "授权管理",
      type = LogTypeEnum.LOGIN,
      level = LogLevelEnum.HIGH_RISK,
      title = "修改密码",
      isSaveRequestData = false)
  public R<Void> changePassword(@Validated @RequestBody ChangePasswordDTO req) {
    // debug环境跳过验证码
    if (!log.isDebugEnabled() || StrUtil.isNotBlank(req.getVerCode())) {
      // 获取redis中的验证码
      String redisCode = StrUtil.toString(redisUtils.get(req.getVerKey()));
      // 判断验证码
      if (StrUtil.isBlank(req.getVerCode())
          || !redisCode.equals(req.getVerCode().trim().toLowerCase())) {
        amsEventPublisher.publishEvent(
            new LoginLogEvent("修改密码", 2, req.getUsername(), "账号密码登录", "验证码不正确"));
        return R.fail("验证码不正确！");
      }
      redisUtils.del(req.getVerKey());
    } else {
      log.debug("当前环境为测试环境，跳过验证码校验,线上请切换环境:{}", log.isDebugEnabled());
    }
    sysUserLoginSvc.changePassword(req);
    return R.success();
  }

  @GetMapping("/getPermissionInfo")
  @Operation(summary = "获取登录用户的权限信息")
  @AutoLog(module = "授权管理", title = "获取登录用户的权限信息", isSaveRequestData = false)
  public R<AuthPermissionVO> getPermissionInfo() {
    return R.success(sysUserLoginSvc.getPermissionInfo());
  }
}
